/*
 * MIT License
 *
 * Copyright (c) 2020 wen.gu <454727014@qq.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/***************************************************************************
* Name: demux_decode_test.cpp
*
* Purpose: demuxer and decoder test case
*
* Developer:
*   wen.gu , 2019-01-02
*
* TODO:
*
***************************************************************************/

/******************************************************************************
**    INCLUDES
******************************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>
#include <string>

#include "mp_plugin.h"
#include "mp_plugin_manager.h"
#include "mp_demux.h"
#include "mp_decoder.h"


#define LOG_TAG "ddt"
#include "mp_log.h"

/******************************************************************************
**    MACROS
******************************************************************************/



/******************************************************************************
**    VARIABLE DEFINITIONS
******************************************************************************/

std::vector<MPTrackInfo> gTrackInfos;

/******************************************************************************
**   FUNCTION DEFINITIONS
******************************************************************************/

MPError processTrakInfo(const MPTrackInfo& info)
{
    gTrackInfos.push_back(info);
    return MP_OK;
}


void demuxDecodeTest()
{
    std::vector<std::string> compList = 
    {
        "av_demux.dll",
        "av_decoder.dll"
    };
    MPPluginManager& amp = MPPluginManager::getInstance();

    MPError ret = amp.loadList(compList);

    if (MP_OK == ret)
    {
        MPDecoder* mpDec = nullptr;
        MPDemux* mpDex = nullptr;

        MPDemuxCreateParam demuxCP;
        MPDecoderCreateParam decCp;

        demuxCP.uri = "Off_My_Mind.mp3";
        demuxCP.addTrack = processTrakInfo;

        ret = amp.find(&demuxCP, (MPComponent**)&mpDex);

        if (MP_OK == ret)
        {
            const MPTrackInfo& orgInfo = gTrackInfos[0];
            MPTrackInfo& info = decCp.info;
            info.category = eMediaCategory::Audio;
            info.format = orgInfo.format;
            info.audio.bitDepth = orgInfo.audio.bitDepth;
            info.audio.channelCount = orgInfo.audio.channelCount;
            info.audio.samplerate = orgInfo.audio.samplerate;

            ret = amp.find(&decCp, (MPComponent**)&mpDec);

            if (MP_OK == ret)
            {
                mpDex->selectTrack(eMediaCategory::Audio, 0);
                MPBuffer*  buf = nullptr;
                MPBuffer* outFrame = nullptr;
                while (ret == MP_OK)
                {
                    ret = mpDex->read(&buf);

                    if ((ret == MP_OK) && (buf->info().id == 0))
                    {
                        ret = mpDec->sendPacket(buf);

                        if (MP_OK != ret)
                        {
                            LOGE("send packet to decoder failed(%d, %s)\n", ret, MPError2Str(ret));
                        }

                        ret = mpDec->receiveFrame(&outFrame);

                        if (MP_OK == ret)
                        {
                            BufferInfo& bi = outFrame->info();

                            LOGD("got frame, (size: %d, cat: %d, pts:%lld(ms))\n",
                                outFrame->size(), bi.category, bi.pts);
                        }
                        else
                        {
                            LOGE("receive frame from decoder failed(%d, %s)\n", ret, MPError2Str(ret));
                        }
                    }
                    else
                    {
                        LOGE("read data from demux failed(%d, %s)\n", ret, MPError2Str(ret));
                    }
                }
            }
            else
            {
                LOGE("load decoder failed(%d, %s)\n", ret, MPError2Str(ret));
            }
        }
        else
        {
            LOGE("load demux component failed(%d, %s)\n", ret, MPError2Str(ret));
        }
    }
    else
    {
        LOGE("load component list failed(%d, %s)\n", ret, MPError2Str(ret));
    }

}